import logging
from django_redis import get_redis_connection
from redis import RedisError
from rest_framework import serializers

logger = logging.getLogger('django')


class ImageCodeCheckSerializer(serializers.Serializer):
    # 定义图片验证码序列化器
    image_code_id = serializers.UUIDField()  # 该字段用于验证图片id
    text = serializers.CharField(max_length=4, min_length=4)  # 用于验证图片验证码信息格式

    def validate(self, attrs):
        # 获取通过查询参数传过来的数据
        image_code_id = attrs["image_code_id"]
        text = attrs["text"]
        # 从redis数据库中查询图片验证码
        redis_conn = get_redis_connection("verify_codes")
        real_image_code_text = redis_conn.get("img_%s" % image_code_id)
        if not real_image_code_text:
            raise serializers.ValidationError("图片验证码过期")
        # 删除图片验证码，目的为了防止别人一直用这个验证码攻击
        try:
            redis_conn.delete("img_%s" % image_code_id)
        except RedisError as e:
            logger.error(e)
        # 比较图片验证码是否一致
        real_image_code_text = real_image_code_text.decode()  # 从redis中取出的数据是byte
        if real_image_code_text.lower() != text.lower():
            raise serializers.ValidationError("图片验证码输入错误")
        # 为了防止单个手机号，在一分钟之内发起多次短信请求
        mobile = self.context["view"].kwargs["mobile"]  # django中类视图对象中的kwargs属性中保存了url参数
        # 使用序列器的时候，DRF中会默认给序列化器对象context属性，context中包含view，request,format,view表示访问的视图对象
        send_flag = redis_conn.get("send_flag_%s" % mobile)
        # 发送短信的时候，设置一个有效期内(时间为60秒)的标记
        if send_flag:
            raise serializers.ValidationError("请求次数过于频繁")
        return attrs  # 验证通过后，把值返回
